package com.erbantou.filemanage.service;

import com.erbantou.filemanage.database.LocalDatabaseRepository;
import com.erbantou.filemanage.entity.filehash.FileHash;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.List;

@Service
@Slf4j
public class FileHashService {

    private final LocalDatabaseRepository localDatabaseRepository;

    @Autowired
    public FileHashService(LocalDatabaseRepository localDatabaseRepository) {
        this.localDatabaseRepository = localDatabaseRepository;
    }

    /**
     * 存储文件哈希值
     *
     * @param objectName 文件名
     * @param fileHash   文件哈希值
     */
    public void storeFileHash(String objectName, String fileHash) {
        FileHash fileHashEntity = new FileHash();
        fileHashEntity.setObjectName(DigestUtils.sha256Hex(objectName));
        fileHashEntity.setHash(fileHash);
        localDatabaseRepository.save(fileHashEntity);
    }

    /**
     * 获取文件哈希值
     *
     * @param objectName 文件名
     * @return 文件哈希值
     */
    public String getFileHash(String objectName) {
        return localDatabaseRepository.findById(DigestUtils.sha256Hex(objectName))
                .map(FileHash::getHash)
                .orElse(null);
    }

    /**
     * 删除文件哈希值
     *
     * @param objectName 文件名
     */
    public void deleteFileHash(String objectName) {
        localDatabaseRepository.deleteById(DigestUtils.sha256Hex(objectName));
    }

    /**
     * 删除文件哈希值
     *
     * @param objectNames 文件名列表
     */
    public void deleteAllFileHash(List<String> objectNames) {
        localDatabaseRepository.deleteAllById(objectNames.stream().map(DigestUtils::sha256Hex).toList());
    }

    /**
     * 计算文件哈希值
     *
     * @param inputStream 输入流
     * @return 文件哈希值字节数组
     * @throws IOException              如果读取过程中发生错误
     * @throws NoSuchAlgorithmException 如果哈希算法不可用
     */
    public byte[] calculateHash(InputStream inputStream) throws IOException, NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
            }
        }
        return digest.digest();
    }

    /**
     * 计算输入字符串的 SHA-256 哈希值。
     *
     * @param calculateValue 需要计算哈希值的字符串
     * @return 计算出的哈希值，使用字节数组表示
     */
    public String calculateHash(String calculateValue) {
        try {
            // 获取 SHA-256 哈希算法的 MessageDigest 实例
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            // 将输入字符串转换为字节数组
            byte[] inputBytes = calculateValue.getBytes();
            // 更新 MessageDigest 实例，用于处理输入字节数据
            digest.update(inputBytes);
            // 计算并返回最终的哈希值
            return Base64.getEncoder().encodeToString(digest.digest());
        } catch (NoSuchAlgorithmException e) {
            log.error("计算哈希值时发生异常", e);
            return calculateValue;
        }
    }
}
